package com.md.api.common.utils;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.DateUtil;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.*;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.md.api.common.exception.BusinessException;
import com.md.api.entity.util.OssPage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.*;

/**
 * @ClassName AliOssUtil
 * @Description 阿里云oss相关工具类
 * @Author zhangyi
 * @Date 2022/5/26 20:00
 * @Version 1.0
 */
@Component
@Slf4j
public class AliOssUtil {
    // 绑定的自有域名
    public static String CUSTOM = "CUSTOM/";
    public static String SYS = "SYS/";
    public static String DOMAIN = "https://photo-oss-file.oss-cn-shanghai.aliyuncs.com/";
    // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    public static String endpoint = "oss-cn-shanghai.aliyuncs.com";
    // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
//    private static String accessKeyId = "LTAI5tAzQVi2KMHjQ379fzZg";
//    private static String accessKeySecret = "nVwV32fernPMz2YfNvf1NGYW7g3wll";
    // 填写Bucket名称，例如examplebucket。
    public static String bucketName = "photo-oss-file";

    public static final String accessKeyId = "LTAI5t8pLaJZgRbQfsZF6UYk";
    public static final String accessKeySecret = "RyKRfekvzWR09GxbZrcNuZ7BfbC8JT";
    public static String uploadEnterpriseLogo(String fileUrl, String fileName) throws Exception  {

        String ossPath = "image/picture/";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossPath.concat(fileName), urlToFile(fileUrl));
        // 如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setHeader(OSSHeaders.CONTENT_DISPOSITION, "inline");
        metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
        metadata.setObjectAcl(CannedAccessControlList.PublicRead);
        putObjectRequest.setMetadata(metadata);

        // 上传文件。
        ossClient.putObject(putObjectRequest);
        // 关闭ossClient
        ossClient.shutdown();

        return DOMAIN.concat(ossPath.concat(fileName));
    }

    /**
     * 上传excel
     *
     * @param workbook
     * @param dir       目录
     * @param excelName 文件名
     * @return
     */
    public static String uploadExcel(XSSFWorkbook workbook, String dir, String excelName) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            workbook.write(bos);
        } catch (IOException e) {
        } finally {
            try {
                bos.close();
            } catch (IOException e) {
            }
        }
        byte[] brray = bos.toByteArray();
        InputStream is = new ByteArrayInputStream(brray);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, dir +  excelName, is);
            // 如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setHeader(OSSHeaders.CONTENT_DISPOSITION, "inline");
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            putObjectRequest.setMetadata(metadata);

            // 上传文件
            ossClient.putObject(putObjectRequest);
            // 关闭ossClient
            ossClient.shutdown();
            return DOMAIN.concat(dir.concat(excelName));

            //设置过期时间
//            LocalDateTime time = LocalDateTime.now().plusDays(5);
//            Date expiration = Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
//            String s = ossClient.generatePresignedUrl(bucketName, dir + "/" + excelName, expiration).toString();
//            return s;
        } catch (OSSException oe) {
            log.error(oe.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }


    public static String uploadExcel(InputStream is, String dir, String excelName) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, dir +  excelName, is);
            // 如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setHeader(OSSHeaders.CONTENT_DISPOSITION, "inline");
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            putObjectRequest.setMetadata(metadata);

            // 上传文件
            ossClient.putObject(putObjectRequest);
            // 关闭ossClient
            ossClient.shutdown();
            return DOMAIN.concat(dir.concat(excelName));

            //设置过期时间
//            LocalDateTime time = LocalDateTime.now().plusDays(5);
//            Date expiration = Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
//            String s = ossClient.generatePresignedUrl(bucketName, dir + "/" + excelName, expiration).toString();
//            return s;
        } catch (OSSException oe) {
            log.error(oe.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }
    public static void deleteExcel(String excelUrl) {
        if (StringUtils.isNotEmpty(excelUrl)) {
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            try {
                boolean b = ossClient.doesObjectExist(bucketName, excelUrl);
                if (b) {
                    ossClient.deleteObject(bucketName, excelUrl);
                }
            } catch (OSSException oe) {
                log.error(oe.getMessage());
            } finally {
                if (null!=ossClient) {
                    ossClient.shutdown();
                }
            }
        }

    }
    /**
     * 将文件上传到阿里OSS
     *
     * @param sourceFilePathName 本地文件
     * @param aimFilePathName    在阿里OSS中保存的可以包含路径的文件名
     * @return 返回上传后文件的访问路径
     * @throws FileNotFoundException
     */
    public static String upload(String sourceFilePathName, String aimFilePathName) throws FileNotFoundException {
        FileInputStream is = new FileInputStream(sourceFilePathName);

        if (aimFilePathName.startsWith("/")) {
            aimFilePathName = aimFilePathName.substring(1);
        }

        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
        ObjectMetadata metadata = new ObjectMetadata();
        int indexOfLastDot = aimFilePathName.lastIndexOf(".");
        String suffix = aimFilePathName.substring(indexOfLastDot);
        metadata.setContentType(getContentType(suffix));
        metadata.setHeader(OSSHeaders.CONTENT_DISPOSITION, "inline");
        metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
        metadata.setObjectAcl(CannedAccessControlList.PublicRead);
        //避免文件覆盖
//        aimFilePathName = aimFilePathName.substring(0, indexOfLastDot) + System.currentTimeMillis() + suffix;

        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, aimFilePathName, is);
        //避免访问时将图片下载下来
        putObjectRequest.setMetadata(metadata);

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ossClient.putObject(putObjectRequest);

        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100);
        URL url = ossClient.generatePresignedUrl(bucketName, aimFilePathName, expiration);

        // 关闭ossClient
        ossClient.shutdown();

        return url.toString();
    }

    /**
     * 网络实现上传头像到OSS
     *
     * @param multipartFile
     * @param dir 用户路径
     * @return
     */
    public static String upload(MultipartFile multipartFile,String dir,String fileName) throws IOException {
        // 获取上传的文件的输入流
        InputStream inputStream = multipartFile.getInputStream();
        // 获取文件名称
//        String fileName = multipartFile.getOriginalFilename();

        // 避免文件覆盖
//        int i = fileName.lastIndexOf(".");
//        String suffix = fileName.substring(i);
//        fileName = fileName.substring(0, i) + System.currentTimeMillis() + suffix;

        // 把文件按照日期进行分类
        // 拼接fileName
        fileName = dir + fileName;

        // 如果需要上传时设置存储类型与访问权限
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));
        // 上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
        putObjectRequest.setMetadata(metadata);

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ossClient.putObject(putObjectRequest);
        //文件访问路径
//        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, fileName, HttpMethod.GET);
//        req.setProcess("image/info");
//        URL url = ossClient.generatePresignedUrl(req);

//        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100);
//        URL url = ossClient.generatePresignedUrl(bucketName, fileName, expiration);
        // 关闭ossClient
        ossClient.shutdown();
        // 把上传到oss的路径返回
//        return DOMAIN.concat(url.getPath());
        return DOMAIN.concat(fileName);
    }

    /**
     * 返回contentType
     *
     * @param FileNameExtension
     * @return
     */
    private static String getContentType(String FileNameExtension) {
        if (FileNameExtension.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (FileNameExtension.equalsIgnoreCase(".json")) {
            return "application/json";
        }
        if (FileNameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (FileNameExtension.equalsIgnoreCase(".jpeg") ||
                FileNameExtension.equalsIgnoreCase(".jpg") ||
                FileNameExtension.equalsIgnoreCase(".png")
        ) {
            return "image/jpg";
        }
        return "image/jpg";
    }

    /**
     * 分页获取纯图片的网页地址
     * @return
     */
    public static OssPage pageOss(OssPage page){
        List<com.md.api.entity.util.OSSObject> result = new ArrayList<>();
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
        listObjectsRequest.setMaxKeys(page.getLimit());
        if (StringUtils.isNotEmpty(page.getMarker())){
            listObjectsRequest.setMarker(page.getMarker());
        }
        listObjectsRequest.setPrefix(page.getPrefix());
        ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
        for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
            // 处理objectSummary，例如打印文件名。
            String key = objectSummary.getKey();
            com.md.api.entity.util.OSSObject object = new com.md.api.entity.util.OSSObject();
            if (key.endsWith("/")) {
                object.setFileType("folder");
            } else {
                object.setFileType("file");
            }
            object.setUrl(DOMAIN.concat("/").concat(key));
            object.setFileKey(key.replaceAll(page.getPrefix(),""));
            object.setSize(objectSummary.getSize());
            object.setLastUpdateTime(objectSummary.getLastModified());
            result.add(object);
        }
        page.setNextMarker(objectListing.getNextMarker());
        page.setList(result);
        // 关闭OSSClient。
        ossClient.shutdown();
        return page;
    }



    /**
     * 列举 指定路径下所有的文件的文件名
     * 如果要列出根路径下的所有文件，path= ""
     *
     * @param path
     * @return
     */
    public static List<String> listFileName(String path) {
        List<String> res = new ArrayList<>();
        // 构造ListObjectsRequest请求。
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);

        // 设置prefix参数来获取fun目录下的所有文件。
        listObjectsRequest.setPrefix(path);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 列出文件。
        ObjectListing listing = ossClient.listObjects(listObjectsRequest);
        // 遍历所有文件
        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
            System.out.println(objectSummary.getKey());
        }
        // 关闭OSSClient。
        ossClient.shutdown();
        return res;
    }
    public static List<OSSObjectSummary> listFile(String path) {
        List<String> res = new ArrayList<>();
        // 构造ListObjectsRequest请求。
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);

        // 设置prefix参数来获取fun目录下的所有文件。
        listObjectsRequest.setPrefix(path);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 列出文件。
        ObjectListing listing = ossClient.listObjects(listObjectsRequest);
        // 关闭OSSClient。
        ossClient.shutdown();
        return listing.getObjectSummaries();
    }

    /**
     * 获取文件夹大小
     */
    public static long getFolderSize(String path) {
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        long folderSize=0;
        boolean res = isFolderExist(path);
        if (!res){//文件夹是否存在
            return folderSize;
        }
        ObjectListing listing = client.listObjects(bucketName, path);
        // 遍历所有Object
        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
            System.out.println(objectSummary.getKey());
            System.out.println(objectSummary.getSize());//输出每个object文件的大小
            folderSize = folderSize+objectSummary.getSize();
        }
        return folderSize;
    }
    /**
     * 删除文件
     *
     * @param fullPath 文件名称，图片名称包括文件夹名称和“/”
     */
    public static boolean delShopImage(String fullPath) {
        String fileName = fullPath.replace(DOMAIN,"");
        if (fileName.startsWith("/")){
            fileName = fileName.replaceFirst("/","");
        }
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        //判断文件是否存在
        boolean exist = ossClient.doesObjectExist(bucketName, fileName);
        //文件不存在删除失败
        if (!exist) {
            return false;
        }
        try {
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, fileName);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return true;
    }



    public static Long getFileSize(String fullPath) {
        try {
            String fileName = URLDecoder.decode(fullPath,"UTF-8").replace(DOMAIN,"");
            if (fileName.startsWith("/")){
                fileName = fileName.replaceFirst("/","");
            }
            OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            long size = client.getObjectMetadata(bucketName, fileName).getContentLength();
            return size;
        }catch (Exception e){
            e.printStackTrace();
            return 0l;
        }
    }


    /**
     * 列举文件下所有的文件url信息
     */
    public static List<String> listFileUrl(String path) {
        List<String> res = new ArrayList<>();

        // 构造ListObjectsRequest请求
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);

        // 设置prefix参数来获取fun目录下的所有文件。
        listObjectsRequest.setPrefix(path);

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 列出文件。
        ObjectListing listing = ossClient.listObjects(listObjectsRequest);
        // 遍历所有文件。

        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
            //文件访问路径
            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100);
            URL url = ossClient.generatePresignedUrl(bucketName, objectSummary.getKey(), expiration);
            res.add(url.toString());
        }
        // 关闭OSSClient。
        ossClient.shutdown();
        return res;
    }

    /**
     * 判断文件夹是否存在
     *
     * @param path
     * @return
     */
    public static boolean isFolderExist(String path) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 构造模拟文件夹路径的列表请求
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
            listObjectsRequest.setPrefix(path);
            listObjectsRequest.setDelimiter("/");

            // 列出文件夹下的内容
            ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
            if (objectListing.getCommonPrefixes() != null && !objectListing.getCommonPrefixes().isEmpty()) {
                // 如果返回的公共前缀列表不为空，则表明文件夹存在
                System.out.println("文件夹存在：" + path);
                return true;
            } else {
                System.out.println("文件夹不存在：" + path);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }
        return false;
    }
    /**
     * 判断文件是否存在
     *
     * @param objectName
     * @return
     */
    public static boolean isFileExist(String objectName) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        boolean res = ossClient.doesObjectExist(bucketName, objectName);
        return res;
    }


    //修改文件存储类型
    public static void resetStorageClass(String path,StorageClass storageClass){
        String objectName = path.replaceAll(DOMAIN.concat("/"),"");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建CopyObjectRequest对象。
            CopyObjectRequest request = new CopyObjectRequest(bucketName, objectName, bucketName, objectName) ;

            // 创建ObjectMetadata对象。
            ObjectMetadata objectMetadata = new ObjectMetadata();

            objectMetadata.setHeader("x-oss-storage-class", storageClass);
            request.setNewObjectMetadata(objectMetadata);

            // 更改文件存储类型。
            CopyObjectResult result = ossClient.copyObject(request);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
    //解冻归档文件
    public static void thawingFile(String path){

        String objectName = path.replaceAll(DOMAIN.concat("/"),"");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            ObjectMetadata objectMetadata = ossClient.getObjectMetadata(bucketName, objectName);
            // 校验Object是否为归档类型Object。
            StorageClass storageClass = objectMetadata.getObjectStorageClass();
            if (storageClass == StorageClass.Archive) {
                // 解冻Object。
                ossClient.restoreObject(bucketName, objectName);
                // 等待解冻完成。
                do {
                    Thread.sleep(1000);
                    objectMetadata = ossClient.getObjectMetadata(bucketName, objectName);
                } while (!objectMetadata.isRestoreCompleted());
            }
            // 获取解冻Object。
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            ossObject.getObjectContent().close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    //解冻冷归档文件
    public static void thawingColdFile(String path){

        String objectName = path.replaceAll(DOMAIN.concat("/"),"");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 设置解冻冷归档Object的优先级。
            // RestoreTier.RESTORE_TIER_EXPEDITED 表示1小时内完成解冻。
            // RestoreTier.RESTORE_TIER_STANDARD 表示2~5小时内完成解冻。
            // RestoreTier.RESTORE_TIER_BULK 表示5~12小时内完成解冻。
            RestoreJobParameters jobParameters = new RestoreJobParameters(RestoreTier.RESTORE_TIER_EXPEDITED);

            // 配置解冻参数，以设置5小时内解冻完成，解冻状态保持2天为例。
            // 第一个参数表示保持解冻状态的天数，默认是1天，此参数适用于解冻Archive（归档）与ColdArchive（冷归档）类型Object。时间到自动回到冷冻状态
            // 第二个参数jobParameters表示解冻优先级，只适用于解冻ColdArchive类型Object。
            RestoreConfiguration configuration = new RestoreConfiguration(2, jobParameters);

            // 发起解冻请求。
            ossClient.restoreObject(bucketName, objectName, configuration);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    //解冻深度冷归档文件
    public static void thawingDeepColdFile(String path){

        String objectName = path.replaceAll(DOMAIN.concat("/"),"");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 配置解冻优先级。本代码示例以RESTORE_TIER_STANDARD为例。
            // RestoreTier.RESTORE_TIER_EXPEDITED: 12个小时之内解冻完成。
            // RestoreTier.RESTORE_TIER_STANDARD: 48小时之内解冻完成。
            RestoreJobParameters jobParameters = new RestoreJobParameters(RestoreTier.RESTORE_TIER_STANDARD);

            // 配置解冻状态持续时间，默认为1天。本代码示例以解冻状态持续时间为1天为例。时间到自动回到冷冻状态
            RestoreConfiguration configuration = new RestoreConfiguration(2, jobParameters);

            // 发起解冻请求。
            ossClient.restoreObject(bucketName, objectName, configuration);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public static boolean getThawingStatus(String path){

        String objectName = path.replaceAll(DOMAIN.concat("/"),"");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            HeadObjectRequest req=new HeadObjectRequest(bucketName,objectName);
            ObjectMetadata objectMetadata = ossClient.headObject(req);
            Map<String, Object> rawMetadata = objectMetadata.getRawMetadata();
            if (null!=rawMetadata) {
                log.info(JsonUtils.toJsonString(rawMetadata));
                if (null!=rawMetadata.get("x-oss-restore")) {
                    String o = rawMetadata.get("x-oss-restore").toString();
                    if (o.contains("ongoing-request=\"false\"")) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return false;
    }


    //设置生命周期规则
    public static void setLifecycle(String ruleId,String prefix,int expirationDays,StorageClass storageClass){
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            SetBucketLifecycleRequest request = new SetBucketLifecycleRequest(bucketName);

            LifecycleRule rule = new LifecycleRule(ruleId,prefix, LifecycleRule.RuleStatus.Enabled);
            List<LifecycleRule.StorageTransition> storageTransitions = new ArrayList<LifecycleRule.StorageTransition>();
            LifecycleRule.StorageTransition storageTransition = new LifecycleRule.StorageTransition();
            storageTransition.setStorageClass(storageClass);
            storageTransition.setExpirationDays(expirationDays);
            storageTransitions.add(storageTransition);
            rule.setStorageTransition(storageTransitions);
            request.AddLifecycleRule(rule);

            // 发起设置生命周期规则请求。
            ossClient.setBucketLifecycle(request);

            // 查看生命周期规则。
            List<LifecycleRule> listRules = ossClient.getBucketLifecycle(bucketName);
            for(LifecycleRule rules : listRules){
                System.out.println("ruleId="+rules.getId()+", matchPrefix="+rules.getPrefix());
            }
        } catch (Exception e) {
           e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    /**
     * 通过文件名下载文件
     *
     * @param objectName    要下载的文件名
     * @param localFileName 本地要创建的文件名
     */
    public static void downloadFile(String objectName, String localFileName) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(localFileName));
        // 关闭OSSClient。
        ossClient.shutdown();
    }


    /**
     * 创建文件夹
     *
     * @param folder
     * @return
     */
    public static String createFolder(String folder) {
        if (!folder.endsWith("/")){
            throw new BusinessException("文件夹必须以/结尾！");
        }
        // 文件夹名
        final String keySuffixWithSlash = folder;
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 判断文件夹是否存在，不存在则创建
        if (!ossClient.doesObjectExist(bucketName, keySuffixWithSlash)) {
            // 创建文件夹
            ossClient.putObject(bucketName, keySuffixWithSlash, new ByteArrayInputStream(new byte[0]));
            // 得到文件夹名
            OSSObject object = ossClient.getObject(bucketName, keySuffixWithSlash);
            String fileDir = object.getKey();
            ossClient.shutdown();
            return fileDir;
        }

        return keySuffixWithSlash;
    }

    /**
     * url地址资源转化为file流
     * @param urlPath
     * @return
     */
    public static File urlToFile(String urlPath) {

        URLConnection urlConn = null;
        InputStream is = null;
        File file = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(urlPath);
            urlConn = url.openConnection();
            is = urlConn.getInputStream();

            file = File.createTempFile("tmp", null);
            fos = new FileOutputStream(file);
            byte[] buffer = new byte[4096];
            int length;
            while ((length = is.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
            return file;
        } catch (IOException e) {
            return null;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ignored) {
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException ignored) {
                }
            }
        }
    }



    /**
     * 将输入流转换成字节输出流
     * @param is 输入流（谁传谁关）
     * @return writer（谁得谁关）
     * @throws IOException
     */
    public static ByteArrayOutputStream readInputStream(InputStream is){
        ByteArrayOutputStream steram = new ByteArrayOutputStream();
        try {
            byte[] buff = new byte[1024 * 2];
            int len = 0;
            while ((len = is.read(buff)) != -1) {
                steram.write(buff, 0, len);
            }
        }catch (Exception e) {
            try {
                if(steram != null) steram.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            return null;
        }
        return steram;
    }


    public static String ftpToOss(String dir, String fileName) throws IOException {
        // FTP配置
        String ftpHost = "ftp.yourhost.com";
        int ftpPort = 21;
        String ftpUser = "username";
        String ftpPass = "password";


        // 连接FTP服务器
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(ftpHost, ftpPort);
        ftpClient.login(ftpUser, ftpPass);

        // 下载文件
        File localFile = File.createTempFile("ftp-", null);
        boolean success = ftpClient.retrieveFile("/path/to/your/file/on/ftp", new FileOutputStream(localFile));
        if (success) {
            System.out.println("File downloaded successfully.");
        }

        // 关闭FTP连接
        ftpClient.logout();
        ftpClient.disconnect();

        // 创建OSS客户端
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 上传文件到OSS
        ossClient.putObject(bucketName, fileName, localFile);

        // 关闭OSS客户端
        ossClient.shutdown();

        // 删除本地临时文件
        localFile.delete();

        System.out.println("File uploaded to OSS successfully.");
        return DOMAIN.concat(dir.concat(fileName));
    }


    public static void main(String[] args) {
        System.out.println(getFileSize(URLDecoder.decode("https://photo-oss-file.oss-cn-shanghai.aliyuncs.com/CUSTOM/e92ca8691fe1c5e61c1f83901ee8eba5/%E4%B8%8B%E8%BD%BD1716366758302.jpeg")));
    }
    //前端获取临时token
    public static String getTemporaryToken(String userId) {
        // 从环境变量中获取步骤3生成的RAM角色的RamRoleArn。
        String roleArn = System.getenv("OSS_STS_ROLE_ARN");
        // 自定义角色会话名称，用来区分不同的令牌，例如可填写为SessionTest。
        String roleSessionName = userId;
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket下的src目录上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集，即仅允许将文件上传至目标存储空间examplebucket下的src目录。
        // 如果policy为空，则用户将获得该角色下所有权限。
//        String policy = "{\n" +
//                "    \"Version\": \"1\", \n" +
//                "    \"Statement\": [\n" +
//                "        {\n" +
//                "            \"Action\": [\n" +
//                "                \"oss:PutObject\"\n" +
//                "            ], \n" +
//                "            \"Resource\": [\n" +
//                "                \"acs:oss:*:*:"+bucketName+"*\" \n" +
//                "            ], \n" +
//                "            \"Effect\": \"Allow\"\n" +
//                "        }\n" +
//                "    ]\n" +
//                "}";
        // 设置临时访问凭证的有效时间为3600秒。
        Long durationSeconds = 3600L;
        try {
            // regionId表示RAM的地域ID。以华东1（杭州）地域为例，regionID填写为cn-hangzhou。也可以保留默认值，默认值为空字符串（""）。
            String regionId = "cn-shanghai";
            // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
            DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
            // 添加endpoint。适用于Java SDK 3.12.0以下版本。
            // DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            // 适用于Java SDK 3.12.0以下版本。
            //request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
//            request.setPolicy(policy);
            request.setDurationSeconds(durationSeconds);
            final AssumeRoleResponse response = client.getAcsResponse(request);
            System.out.println("Expiration: " + response.getCredentials().getExpiration());
            System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
            System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
            System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
            System.out.println("RequestId: " + response.getRequestId());
            return response.getCredentials().getSecurityToken();
        } catch (ClientException e) {
            System.out.println("Failed：");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());
            return null;
        }
    }




}
